<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Comparison of Modules and Objects
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora152.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora154.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Comparison of Modules and Objects</H2>The main difference between modular programming and object
programming in Objective CAML comes from the type system.
In effect, programming with modules remains within
the ML type system (i.e. parametric polymorphism code is
executed for different types of parameter), while programming with
objects entails an ad hoc polymorphism (in which the sending of
a message to an object triggers the application of different pieces of
code). This is particularly clear with subtyping. This extension of
the ML type system can not be simulated in pure ML. It will
always be impossible to construct heterogeneous lists without breaking
the type system.<BR>
<BR>
Modular programming and object programming are two safe (thanks to
typing) approaches to the logical organisation of a program,
permitting the reusability and the modifiability of software
components. Programming with objects in Objective CAML allows parametric
polymorphism (parameterized classes) and <EM>inclusion/subtype
polymorphism</EM> (sending of messages) thanks to late binding and
subtyping, with restrictions due to equality, facilitating
incremental programming. Modular programming allows one to restrict
parametric polymorphism and use immediate binding, which can be useful
for conserving efficiency of execution.<BR>
<BR>
The modular programming model permits the easy extension of functions
on non-extensible recursive data types. If one wishes to add a case in
a variant type, it will be necessary to modify a large part of the
sources. <BR>The object model of programming defines a set of recursive
data types using classes. One interprets a class as a case of the
data type.<BR>
<BR>

<H4> Efficiency of Execution</H4>
Late binding corresponds to an indirection in the method table (see page 
<A HREF="book-ora142.html#sec-dispatch">??</A>). Just as the access to an instance variable from
outside the class goes through a message dispatch, this
accumulation of indirections can prove to be costly.<BR>
<BR>
To show this loss of efficiency, we construct the following class hierarchy:


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE>test<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>sum<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>sum2<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>a<CODE> </CODE>x<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>test<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>a<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>a<CODE> </CODE><CODE>=</CODE><CODE> </CODE>a<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>sum<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>a<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>sum2<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self#a<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR># <B>class</B><CODE> </CODE>b<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>a<CODE> </CODE>x<CODE> </CODE><B>as</B><CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>b<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>b<CODE> </CODE><CODE>=</CODE><CODE> </CODE>b<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><CODE> </CODE>sum<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>b<CODE> </CODE><CODE>+</CODE><CODE> </CODE>a<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><CODE> </CODE>sum2<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self#b<CODE> </CODE><CODE>+</CODE><CODE> </CODE>super#sum2()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
Now, we compare the execution time, on one hand of the dispatch of
messages <TT>sum</TT> and <TT>sum2</TT> to an instance of class
<TT>b</TT>, and on the other hand of a call to the following function
<TT>f</TT>.


<PRE><BR># <B>let</B><CODE> </CODE>f<CODE> </CODE>a<CODE> </CODE>b<CODE> </CODE><CODE>=</CODE><CODE> </CODE>a<CODE> </CODE><CODE>+</CODE><CODE> </CODE>b<CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>iter<CODE> </CODE>g<CODE> </CODE>a<CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><B>to</B><CODE> </CODE>n<CODE> </CODE><B>do</B><CODE> </CODE>ignore<TT>(</TT>g<CODE> </CODE>a<TT>)</TT><CODE> </CODE><B>done</B><CODE> </CODE>;<CODE> </CODE>g<CODE> </CODE>a<CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>go<CODE> </CODE>i<CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>match</B><CODE> </CODE>i<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE>-&gt;<CODE> </CODE>iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x#sum()<TT>)</TT><CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>b<CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE>j<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>2</CODE><CODE> </CODE>-&gt;<CODE> </CODE>iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>x#sum2()<TT>)</TT><CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>b<CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE>j<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>3</CODE><CODE> </CODE>-&gt;<CODE> </CODE>iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>f<CODE> </CODE><CODE>1</CODE><CODE> </CODE>x<TT>)</TT><CODE> </CODE><CODE>2</CODE><CODE> </CODE>j<CODE> </CODE>;;<BR><BR># go<CODE> </CODE><TT>(</TT>int_of_string<CODE> </CODE><TT>(</TT>Sys.argv<CODE>.</CODE><TT>(</TT><CODE>1</CODE><TT>)</TT><TT>)</TT><TT>)</TT><CODE> </CODE><TT>(</TT>int_of_string<CODE> </CODE><TT>(</TT>Sys.argv<CODE>.</CODE><TT>(</TT><CODE>2</CODE><TT>)</TT><TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
For 10 million iterations, we get the following results:
<DIV ALIGN=center>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1>
<TR><TD  ALIGN=left NOWRAP>&nbsp;</TD>
<TD  ALIGN=left NOWRAP>bytecode</TD>
<TD  ALIGN=left NOWRAP>native</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>case 1</TD>
<TD  ALIGN=left NOWRAP>07,5 s</TD>
<TD  ALIGN=left NOWRAP>0,6 s</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>case 2</TD>
<TD  ALIGN=left NOWRAP>15,0 s</TD>
<TD  ALIGN=left NOWRAP>2,3 s</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>case 3</TD>
<TD  ALIGN=left NOWRAP>06,0 s</TD>
<TD  ALIGN=left NOWRAP>0,3 s</TD>
</TR></TABLE>
</DIV><BR>
This example has been constructed in order to show that late
binding has a cost relative to the standard static binding. This cost
depends on the quantity of calculation relative to the number of
message dispatches in a function. The use of the native compiler
reduces the calculation component without changing the indirection
component of the test. We can see in case 2 that
the multiple indirections at the dispatch of message
<TT>sum2</TT> have an ``incompressible'' cost.<BR>
<BR>

<H4> Example: Graphical Interface</H4>The <TT>AWI</TT> graphical library (see page <A HREF="book-ora124.html#sec-UPI">??</A>) was
designed using the functional/imperative core of the language. It is
very easy to adapt it into module form. Each component becomes an
independent module, thus permitting a harmonization of function names.
To add a component, it is necessary to know the concrete type of its
components. It is up to the new module to modify the fields necessary
to describe its appearance and its behaviors.<BR>
<BR>
The library can also be rewritten as an object. For this we construct the
hierarchy of classes shown in figure <A HREF="book-ora153.html#fig-rep-classe-upi">16.1</A>.<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<IMG SRC="book-ora065.gif">
</DIV>
<BR>
<DIV ALIGN=center>Figure 16.1: Class hierarchy for <TT>AWI</TT>.</DIV><BR>

<A NAME="fig-rep-classe-upi"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>It is easier to add new components, thanks to inheritance, than when
using modules; however, the absence of overloading still requires
options to be encoded as method parameters. The use of
the subtyping relation makes it easy to construct a list of
the constituents of a container. Deferred linking selects
the methods appropriate to the component. The interest
of the object model also comes from the possibility of extending or
modifying the graphics context, and the other types that are used,
again thanks to inheritance. This is why the principal 
graphics libraries are organised according to the object model.<BR>
<BR>
<A NAME="toc221"></A>
<H3> Translation of Modules into Classes</H3>A simple module which only declares one type and does not have any
type-independent polymorphic functions can be translated into a
class. According to the nature of the type used (record type or
variant type) one translates the module into a class in a different
way.<BR>
<BR>

<H4> Type Declarations</H4>
<H5> Record type.</H5>
A record type can be written directly in the form of a class
in which every field of the record type becomes an instance variable.<BR>
<BR>

<H5> Variant type.</H5>A variant type translates into many classes, using the conceptual
model of a ``composite''. An abstract class describes the operations
(functions) on this type. Every branch of the variant type thus
becomes a subclass of the abstract class, and implements the abstract
methods for its branch. We no longer have pattern
matching but instead choose the method specific to the branch.<BR>
<BR>

<H5> Parameterized types.</H5>
Parameterized types are implemented by parameterized classes.<BR>
<BR>

<H5> Abstract types.</H5>We can consider a class as an abstract type. At no time is the
internal state of the class visible outside its hierarchy.
Nevertheless, nothing prevents us from defining a subclass in
order to access the variables of the instances of a class.<BR>
<BR>

<H5> Mutually recursive types.</H5>The declarations of mutually recursive types are translated into
declarations of mutually recursive classes.<BR>
<BR>

<H4> Function Declarations</H4>Those functions with parameters dependent on the module type,
<I>t</I>, are translatable into methods. Functions in which
<I>t</I> does not appear may be declared <B>private</B> inasmuch as
their membership of the module is not directly linked to the type
<I>t</I>. This has the added advantage that there is no
problem if type variables appear in the type of the parameters. We
are left with the problem of functions in which one parameter is of
type <I>t</I> and another is of type <I>'a</I>. These functions
are very rare in the modules of the standard library. We can identify
``peculiar'' modules like <TT>Marshal</TT> or <TT>Printf</TT> which
have non-standard typing, and modules (that operate) on linear
structures like <TT>List</TT>. For this last, the function
<TT>fold_left</TT>, of type <I>('a -&gt; 'b -&gt; 'a) -&gt; 'a -&gt; 'b list -&gt; 'a</I> is
difficult to translate, especially in a method of the class
<I>['b] list</I> because the type variable <I>'a</I> is free and
may not appear in the type of the method. Rather than adding a type
parameter to the <TT>list</TT> class, it is preferable to break these
functions out into new classes, parameterized by two type variables
and having a list field.<BR>
<BR>

<H5> Binary methods.</H5>
Binary methods do not pose any problem, outside subtyping.<BR>
<BR>

<H5> Other declarations.</H5>Declarations of non-functional values. We can accept the declaration
of non-functional values outside classes. This is also true for
exceptions.<BR>
<BR>

<H5> Example: Lists with Iterator.</H5>We are trying to translate a module with the following signature <TT>LIST</TT>
into an object.<BR>
<BR>


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>LIST<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE><CODE>=</CODE><CODE> </CODE>C0<CODE> </CODE><CODE>|</CODE><CODE> </CODE>C1<CODE> </CODE><B>of</B><CODE> </CODE><I>'a</I><CODE> </CODE><CODE>*</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>add<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>length<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>hd<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>tl<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>append<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>fold_left<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'b</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'b</I><CODE> </CODE>list<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><BR><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
First of all, we declare the abstract class <I>'a list</I> corresponding to
the definition of the type.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>list<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'b</I><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>add<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>empty<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>bool<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>hd<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>tl<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>length<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>append<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>list<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
Then we define the two subclasses <TT>c1_list</TT> and
<TT>c0_list</TT> for each constituent of the variant type. Each of
these classes should define the methods of the ancestor abstract class


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT>t<CODE>,</CODE><CODE> </CODE>q<TT>)</TT><CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>list<CODE> </CODE>()<CODE> </CODE><B>as</B><CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><CODE> </CODE>q<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>add<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT>x<CODE>,</CODE><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>#list<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>empty<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>false</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>length<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>+</CODE><CODE> </CODE>q#length()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>hd<CODE> </CODE><CODE>=</CODE><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>tl<CODE> </CODE><CODE>=</CODE><CODE> </CODE>q<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>append<CODE> </CODE>l<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT>t<CODE>,</CODE>q#append<CODE> </CODE>l<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>c0_list<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>list<CODE> </CODE>()<CODE> </CODE><B>as</B><CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>add<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT>x<CODE>,</CODE><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>#list<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>empty<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>true</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>length<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>hd<CODE> </CODE><CODE>=</CODE><CODE> </CODE>failwith<CODE> </CODE><CODE>"c0_list : hd"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>tl<CODE> </CODE><CODE>=</CODE><CODE> </CODE>failwith<CODE> </CODE><CODE>"c0_list : tl"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>append<CODE> </CODE>l<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE>l<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT><CODE>4</CODE><CODE>,</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c1_list<CODE> </CODE><TT>(</TT><CODE>7</CODE><CODE>,</CODE><CODE> </CODE><B>new</B><CODE> </CODE>c0_list<CODE> </CODE>()<TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR><CODE>val l : int list = &lt;obj&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The function <TT>LIST.fold_left</TT> has not been incorporated into
the <TT>list</TT> class to avoid introducing a new type parameter.
We prefer to define the class <TT>fold_left</TT> to implement this
method. For this, we use a functional instance variable
(<TT>f</TT>).


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>,</CODE><I>'b</I><CODE>]</CODE><CODE> </CODE>fold_left<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>f<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'b</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>iter<CODE> </CODE>r<CODE> </CODE><TT>(</TT>l<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'b</I><CODE> </CODE>list<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>l#empty()<CODE> </CODE><B>then</B><CODE> </CODE>r<CODE> </CODE><B>else</B><CODE> </CODE>self#iter<CODE> </CODE><TT>(</TT>self#f<CODE> </CODE>r<CODE> </CODE><TT>(</TT>l#hd<TT>)</TT><TT>)</TT><CODE> </CODE><TT>(</TT>l#tl<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>,</CODE><I>'b</I><CODE>]</CODE><CODE> </CODE>gen_fl<CODE> </CODE>f<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>,</CODE><I>'b</I><CODE>]</CODE><CODE> </CODE>fold_left<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>f<CODE> </CODE><CODE>=</CODE><CODE> </CODE>f<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
Thus we construct an instance of the class <TT>gen_fl</TT> for addition:


<PRE><BR># <B>let</B><CODE> </CODE>afl<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>gen_fl<CODE> </CODE><TT>(</TT><CODE>+</CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>val afl : (int, int) gen_fl = &lt;obj&gt;</CODE><BR># afl#iter<CODE> </CODE><CODE>0</CODE><CODE> </CODE>l<CODE> </CODE>;;<BR><CODE>- : int = 11</CODE><BR>

</PRE>
<BR>
<BR>
<A NAME="toc222"></A>
<H3> Simulation of Inheritance with Modules</H3>Thanks to the relation of inheritance between classes,
we can retrieve in a subclass the collection of variable
declarations and methods of the ancestor class.
We can simulate this relation by
using modules. The subclass which inherits is transformed into a
parameterized module, of which the parameter is the ancestor class.
Multiple inheritance increases the number of parameters of
the module. We revisit the classic example of points and colored
points, described in chapter <A HREF="index.html#chap-POO">15</A>, to translate it into
modules.<BR>
<BR>
The class <TT>point</TT> becomes the module <TT>Point</TT> with the
following signature <TT>POINT</TT>.


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>POINT<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>point<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>new_point<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>point<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>get_x<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>get_y<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>moveto<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>rmoveto<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>display<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>distance<CODE> </CODE><CODE>:</CODE><CODE> </CODE>point<CODE> </CODE>-&gt;<CODE> </CODE>float<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The class <TT>colored_point</TT> is transformed into a parameterized module <TT>ColoredPoint</TT>
which has the signature <TT>POINT</TT> as its parameter.


<PRE><BR># <B>module</B><CODE> </CODE>ColoredPoint<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>functor</B><CODE> </CODE><TT>(</TT>P<CODE> </CODE><CODE>:</CODE><CODE> </CODE>POINT<TT>)</TT><CODE> </CODE>-&gt;<BR><CODE> </CODE><B>struct</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>colored_point<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{p<CODE>:</CODE>P.point;c<CODE>:</CODE>string}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>new_colored_point<CODE> </CODE>p<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{p<CODE>=</CODE>P.new_point<CODE> </CODE>p;c<CODE>=</CODE>c}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>get_c<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>c<BR><CODE> </CODE><CODE>(* begin *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>get_x<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.get_x<CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>get_y<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.get_y<CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>moveto<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.moveto<CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>rmoveto<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.rmoveto<CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>display<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.display<CODE> </CODE>super<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>distance<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.distance<CODE> </CODE>super<BR><CODE> </CODE><CODE>(* end *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>display<CODE> </CODE>self<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>super<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self<CODE>.</CODE>p<CODE> </CODE><B>in</B><CODE> </CODE>P.display<CODE> </CODE>super;<CODE> </CODE>print_string<CODE> </CODE><TT>(</TT><CODE>"has color "</CODE><CODE>^</CODE><CODE> </CODE>self<CODE>.</CODE>c<TT>)</TT><BR><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The burden of ``inherited'' declarations can be lightened by an
automatic translation procedure, or an extension of the language.
Recursive method declarations can be written with a single 
<CODE> let rec ... and</CODE>. Multiple inheritance leads to functors with many
parameters. The cost of redefinition is not greater than that of late
binding.<BR>
<BR>
Late binding is not implemented in this simulation. To achieve it, it
is necessary to define a record in which each field corresponds to the
type of its functions/methods.<BR>
<BR>
<A NAME="toc223"></A>
<H3> Limitations of each Model</H3>The functional/modular module offers a reassuring but rigid framework
for the modifiability of code. Objective CAML's object model suffers from
``double vision'' of classes: structuring and type, implying the
absence of overloading and the impossibility of imposing type
constraints from an ancestor type on a descendant type. <BR>
<BR>

<H4> Modules</H4>The principal limitations of the functional/modular model arise from
the difficulty of extending types. Although abstract types
allow us to get away from the concrete representation of
a type, their use in parameterized modules requires that type
equalities between modules be indicated by hand,
complicating the writing of signatures.<BR>
<BR>

<H5> Recursive dependencies.</H5>The dependence graph of the modules in an application is a
directed acyclic graph (DAG). This implies on the one hand that there
are no types that are mutually recursive between two modules, and on
the other prevents the declaration of mutually recursive values.<BR>
<BR>

<H5> Difficulties in writing signatures.</H5>One of the attractions of type inference is that it is not necessary
to specify the types of function parameters. The specification of
signatures sacrifices this convenience. It becomes necessary to
specify the types of the declarations of the signature ``by hand.''
One can use the <TT>-i</TT> option of the compiler <TT>ocamlc</TT> to
display the type of all the global declarations in a <TT>.ml</TT> file
and use this information to construct the signature of a module. In
this case, we lose the ``software engineering'' discipline which
consists of specifying the module before implementing it. In
addition, if the signature and module undergo large changes, we will
have to go back to editing the signature. Parameterized modules need
signatures for their parameters and those should also be written by
hand. Finally if we associate a functional signature with a
parameterized module, it is impossible to recove the
signature resulting from the application of the functor. This obliges
us to mostly write non-functional signatures, leaving it until
later to assemble them to construct a functional signature.<BR>
<BR>

<H5> Import and export of modules.</H5>The importation of the declarations of a simple module is achieved
either by dot notation (<TT>Module.name</TT>) or directory by the name
of a declaration (<TT>name</TT>) if the model has been opened
(<B>open</B> <TT>Module</TT>). The declaration of the interface of
the imported module is not directly exportable at the level of the
module in process of being defined. It has access to these
declarations, but they are not considered as declarations of the
module. In order to do this it is necessary to declare, in the same
way as the simulation of inheritance, imported values. The same is
true for parameterized modules. The declarations of the module
parameters are not considered as declarations of the current module.<BR>
<BR>

<H4> Objects</H4>The principle limitations of the Objective CAML object model arise from typing.
<UL>
<LI>
 no methods containing parameters of free type;

<LI> difficulty of escaping from the type of a class in one of its methods; 

<LI> absence of type constraint from the ancestor type on its descendant;

<LI> no overloading;
</UL>The most disconcerting point when you start with the object
extension of Objective CAML is the impossibility of constructing methods
containing a parameterized type in which the type parameter is
free. The declaration of a class can be seen as the definition of a new
type, and hence arises the general rule forbidding the presence of variables
with free type in the declaration of a type.
For this reason, parameterized classes are
indispensable in the Objective CAML object model because they permit the
linking of their type variables.<BR>
<BR>

<H5> Absence of overloading.</H5> The Objective CAML object model does not allow method overloading. As the
type of an object corresponds to types of its methods, the fact of
possessing many methods with the same name but different types would
result in numerous ambiguities, due to parametric polymorphism, which
the system could only resolve dynamically. This would be
contradictory to the vision of totally static typing. We
take a class <TT>example</TT> which has two <TT>message</TT> methods, the first
having an integer parameter, and the second a float parameter. Let
<TT>e</TT> be an instance of this class and <TT>f</TT> be the
following function:


<PRE><BR># <B>let</B><CODE> </CODE>f<CODE> </CODE>x<CODE> </CODE>a<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE>x#message<CODE> </CODE>a<CODE> </CODE>;;<BR>

</PRE>

The calls <TT>f e 1</TT> et <TT>f e 1.1</TT> cannot be statically
resolved because there is no information about the class
<TT>example</TT> in the code of the function <TT>f</TT>.<BR>
<BR>
An immediate consequence of this absence is the uniqueness of instance
constructors. The declaration of a class indicates the parameters to
supply to the creation function. This constructor is unique.<BR>
<BR>

<H5> Initialization.</H5> The initialization of instance variables declared in a class can be
problematic when it should be calculated based on the values passed to
the constructor.<BR>
<BR>

<H5> Equality between instances.</H5> The only equality which applies to objects is physical equality.
Structural equality always returns <TT>false</TT> when it is applied
to two physically different objects. This can be surprising inasmuch
as two instances of the same class share the same method table. One
can imagine a physical test on the method table and a structural test
on the values (<TT>val</TT>) of objects. These are the implementation
choices of the linear pattern-matching style.<BR>
<BR>

<H5> Class hierarchy.</H5>There is no class hierarchy in the language distribution. In
fact the collection of libraries are supplied in the form of
simple or parameterized modules. This demonstrates that the object
extension of the language is still stabilizing,
and makes little case for its extensive use.<BR>
<BR>
<HR>
<A HREF="book-ora152.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora154.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
